#pragma once

#include "Common.h"

// 通信抽象实现
namespace rpc
{
    class BaseMessage
    {
    public:
        using ptr = std::shared_ptr<BaseMessage>;

        BaseMessage() {}
        virtual ~BaseMessage() {}

        void setRid(const string &rid)
        {
            _rid = rid;
        }

        void setMtype(MType type)
        {
            _mtype = type;
        }

        const string rid() const
        {
            return _rid;
        }

        MType mtype() const
        {
            return _mtype;
        }

        virtual string serialize() = 0;
        virtual bool unserialize(const string &) = 0;
        virtual bool check() = 0;

    private:
        MType _mtype;
        string _rid;
    };

    class BaseBuffer
    {
    public:
        using ptr = std::shared_ptr<BaseBuffer>;

        virtual size_t readableSize() = 0;
        virtual int32_t peekInt32() = 0;
        virtual void retrieveInt32() = 0;
        virtual int32_t readInt32() = 0;
        virtual string retrieveAsString(size_t len) = 0;
    };

    class BaseProtocol
    {
    public:
        using ptr = std::shared_ptr<BaseProtocol>;

        virtual bool canProcessed(const BaseBuffer::ptr &buf) = 0;
        virtual bool onMessage(const BaseBuffer::ptr &buf, BaseMessage::ptr &msg) = 0;
        virtual string serialize(BaseMessage::ptr &msg) = 0;
    };

    class BaseConnection
    {
    public:
        using ptr = std::shared_ptr<BaseConnection>;

        virtual void send(const BaseMessage::ptr msg) = 0;
        virtual void shutdown() = 0;
        virtual bool connected() = 0;
    };

    using ConnectionCallback = std::function<void(const BaseConnection::ptr &)>;
    using MessageCallback = std::function<void(const BaseConnection::ptr &, BaseMessage::ptr &)>;
    using CloseCallback = std::function<void(const BaseConnection::ptr &)>;

    class BaseService
    {
    public:
        using ptr = std::shared_ptr<BaseService>;

        virtual void setConnectionCallback(const ConnectionCallback &cb)
        {
            _connectCb = cb;
        }

        virtual void setCloseCallback(CloseCallback &cb)
        {
            _closeCb = cb;
        }

        virtual void setMessageCallback(MessageCallback &cb)
        {
            _messageCb = cb;
        }

        virtual void start() = 0;

    protected:
        ConnectionCallback _connectCb;
        MessageCallback _messageCb;
        CloseCallback _closeCb;
    };

    class BaseClient
    {
    public:
        using ptr = std::shared_ptr<BaseClient>;

        virtual void setConnectionCallback(ConnectionCallback &cb)
        {
            _connectCb = cb;
        }

        virtual void setCloseCallback(CloseCallback &cb)
        {
            _closeCb = cb;
        }

        virtual void setMessageCallback(MessageCallback &cb)
        {
            _messageCb = cb;
        }

        virtual void connect() = 0;
        virtual void shutdown() = 0;
        virtual bool send(const BaseMessage::ptr msg) = 0;
        virtual BaseConnection::ptr connection() = 0;
        virtual bool connected() = 0;

    protected:
        ConnectionCallback _connectCb;
        MessageCallback _messageCb;
        CloseCallback _closeCb;
    };

} // rpc